﻿#include "testlistwidget.h"
#include <QMouseEvent>
#include <testlistwidgetitem.h>
#include <QApplication>
#include <QMimeData>
#include <QDrag>
TestListWidget::TestListWidget(QWidget *parent) :
    QListWidget(parent)
{
    //setMouseTracking(true);  //注释与否没有影响
    //setDragEnabled(true);  //注释与否没有影响
    setAcceptDrops(true);
    //setDropIndicatorShown(false);  //注释与否没有影响
    //setDefaultDropAction(Qt::MoveAction);  //注释与否没有影响
}

//拖拽起点
void TestListWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton){
        startPos = event->pos();
    }
}

void TestListWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if((event->pos() - startPos).manhattanLength() > 5) return;

    TestListWidgetItem *item = static_cast<TestListWidgetItem *>(itemAt(event->pos()));
    setCurrentItem(item);
}

void TestListWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton){
//[1]超过规定距离才会触发拖拽，防止手滑...
        if((event->pos() - startPos).manhattanLength() < QApplication::startDragDistance()) return;
//[1]

        TestListWidgetItem *theDragItem = static_cast<TestListWidgetItem *>(itemAt(startPos));
        setCurrentItem(theDragItem);  //拖拽即选中

        theDragRow = row(theDragItem);

//[2]这部分是把拖拽的数据放在QMimeData容器中（参考Qt例程puzzle，使用QByteArray和QDataStream感觉很方便）
        QString text = theDragItem->text();
        QIcon icon = theDragItem->Img;
//        QIcon icon_hover = theDragItem->Img_hover;
        QByteArray itemData;
        QDataStream dataStream(&itemData, QIODevice::WriteOnly);
        dataStream << text << icon << 2;

        QMimeData *mimeData = new QMimeData;
        mimeData->setData(myMimeType(), itemData);
//[2]


//[3]设置拖拽时的缩略图，thumbnail类(找机会我会写一篇单独的文章介绍)是继承自QWidget的类椭圆形半透明窗口，使用grab()将QWidget变成QPixmap。
//        thumbnail *DragImage = new thumbnail(this);
//        DragImage->setupthumbnail(icon_hover, text);
//        //DragImage->setIconSize(18);  //default:20
//        QPixmap pixmap = DragImage->grab();
         QPixmap pixmap;
        QDrag *drag = new QDrag(this);
        drag->setMimeData(mimeData);
        //设置缩略图
        drag->setPixmap(pixmap);
        //设置鼠标在缩略图上的位置
        drag->setHotSpot(QPoint(pixmap.width()/2, pixmap.height()/2));
//[3]

        //拖拽开始！
        if(drag->exec(Qt::MoveAction) == Qt::MoveAction){
        }
    }
}

void TestListWidget::dragEnterEvent(QDragEnterEvent *event)
{
    TestListWidget *source = qobject_cast<TestListWidget *>(event->source());
    if (source && source == this) {
        //IsDraging(标志位)判断是否正在拖拽
        IsDraging = true;
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}

//当拖拽离开QListWidget时，需要update以保证DropIndicator消失
void TestListWidget::dragLeaveEvent(QDragLeaveEvent *event)
{
    theHighlightedRow = -2;
    update(theHighlightedRect);

    //IsDraging(标志位)判断是否正在拖拽
    IsDraging = false;

    event->accept();
}

//拖拽移动时刷新以更新DropIndicator
void TestListWidget::dragMoveEvent(QDragMoveEvent *event)
{
    TestListWidget *source = qobject_cast<TestListWidget *>(event->source());
    if (source && source == this) {

        oldHighlightedRect = theHighlightedRect;
        theHighlightedRect = targetRect(event->pos());

        //offset() = 19(这个数值是我调用父类的dropEvent(event)一次一次试出来的，我觉得公式应该是19 = 40 / 2 - 1， 其中40是item行高)
        if(event->pos().y() >= offset()){

            theHighlightedRow = row(itemAt(event->pos() - QPoint(0, offset())));

            if(oldHighlightedRect != theHighlightedRect){
                update(oldHighlightedRect);  //刷新旧区域使DropIndicator消失
                update(theHighlightedRect);  //刷新新区域使DropIndicator显示
            }else
                update(theHighlightedRect);
        }else{
            theHighlightedRow = -1;
            update(QRect(0, 0, width(), 80));  //仅刷新第一行
        }

        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}

void TestListWidget::dropEvent(QDropEvent *event)
{
    TestListWidget *source = qobject_cast<TestListWidget *>(event->source());
    if (source && source == this){

        IsDraging = false;  //拖拽完成

        theHighlightedRow = -2;
        update(theHighlightedRect);  //拖拽完成，刷新以使DropIndicator消失

        QListWidget::dropEvent(event);  //因为是拖拽即选中，所以可以直接调用父类的dropEvent(event)

        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}

const QRect TestListWidget::targetRect(const QPoint &position) const
{
    //40是item的行高
    if(position.y() >= offset())
        return QRect(0, (position.y() - offset()) / 40 * 40, width(), 2 * 40);
    else
        return QRect(0, 0, width(), 40);
}
